-------------------------------------------------------------------------------------
-- -*- coding: utf-8 -*-
--
-- @author:   zxf
-- @email:    07291@qq.com
-- @date:     2024/7/22
-- @module:   owner_base
-- @describe:
-- @version:  v1.0
--

-------------------------------------------------------------------------------------

---@type state_manager_base
local state_manager_base = import('bt/bt_framework/state/state_manager_base')
---@type MAIN_TARGET_TYPE_CONFIG
local MAIN_TARGET_TYPE_CONFIG = import('bt/custom_node/enum_type_cfg/MAIN_TARGET_TYPE_CONFIG')
local MAIN_TARGET_TYPE = MAIN_TARGET_TYPE_CONFIG.TYPE
---@type main_target
local main_target = import('bt/bt_framework/func/main_target')
---@type property_base
local property_base = import('bt/bt_framework/property_base')
---@type TimerManager
local TimerManager = import('bt/bt_framework/TimerManager')

---@class owner_base
local owner_base = {}
owner_base.nodeTimers = {}                          --- 节点定时器
owner_base.recordData = {}                          --- 记录数据
owner_base.failNodes = {}                           --- 失败节点
owner_base.isFailProperty = property_base:new()     --- 失败属性
owner_base.timerManager = TimerManager:new()        --- 定时器管理器
owner_base.curTickData = {}                         --- 帧数据
owner_base.m_mainTargetData = {
    curMainTarget = MAIN_TARGET_TYPE.NONE,          --- 当前主目标
    lastMainTarget = MAIN_TARGET_TYPE.NONE,         --- 上一次主目标
    curMainTargetCompleteState = nil,               --- 当前主目标完成状态
    curMainTargetArr = {},                          --- 当前主目标列表
    mainTargetCompleteInsertDic = nil,              --- 主目标完成后插入的目标字典
    breakMainTargetData = nil,                      --- 打断目标的数据
}
owner_base.stateManager = state_manager_base:new()  --- 状态管理器

-- 【外部】清理数据
function owner_base:clear_data()
    xxmsg('清理owner数据')
    self.nodeTimers = {}
    self.failNodes = {}
    self.recordData = {}
    self.curTickData = {}
    self.timerManager:clear()
    self.stateManager:clear_data()
    self:clear_all_main_target_data()
    self:on_clear_data()
end

--- 【外部】检测是否改变主目标
function owner_base:is_change_mainTarget()
    return self.stateManager:curState_needFirstExecute()
end

--- 【外部】检测当前主目标为指定类型
function owner_base:check_curMainTarget(type)
    return self.m_mainTargetData.curMainTarget == type
end

--- 【外部】获取当前主目标
function owner_base:get_curMainTarget()
    return self.m_mainTargetData.curMainTarget
end

--- 【外部】获取上一次主目标
function owner_base:get_lastMainTarget(type)
    return self.m_mainTargetData.lastMainTarget
end

--- 【外部】检测上一次主目标
function owner_base:check_lastMainTarget(type)
    return self.m_mainTargetData.lastMainTarget == type
end

--- 【外部】打断主目标
--- @param targetName string 打断的目标
--- @param notCheckPriority boolean 不检查优先级
--- @param mainTargetData any 当前目标附带的数据
function owner_base:break_main_target(targetName, notCheckPriority, mainTargetData)
    if main_target.check_break_main_target(self, targetName, notCheckPriority) then
        local needStop = false
        local compareCfg = main_target.get_main_target_priority_config(targetName)
        local customCfg = main_target.get_custom_main_target_priority_config(self:get_curMainTarget())
        if customCfg and customCfg[targetName] then
            compareCfg = customCfg[targetName]
        end
        needStop = compareCfg.needStop
        self:set_breakMainTargetData({
            mainTarget = targetName,
            notCheckPriority = notCheckPriority,
            data = mainTargetData
        })
        self:change_state(targetName, needStop)
        return true
    end
    return false
end

--- 【外部】 通过名字移除目标
function owner_base:remove_main_target(mainTargetType)
    if self:check_curMainTarget(mainTargetType) then
        self:set_cur_main_target_complete_state(true)
    else
        self.stateManager:on_remove_mainTarget(mainTargetType)
        main_target.remove_main_target(self, mainTargetType)
    end
end


--- 【外部】添加完成主目标后需要插入的目标
function owner_base:add_complete_mainTarget_to_dic(name, mainTargetName, mainTargetData, insertCond)
    local tmpArrData = self:get_complete_mainTarget_from_dic(name)
    if not tmpArrData then
        self.m_mainTargetData.mainTargetCompleteInsertDic[name] = {}
        tmpArrData = self.m_mainTargetData.mainTargetCompleteInsertDic[name]
    end
    for _, v in ipairs(tmpArrData) do
        local tmpData = v.data
        if tmpData.mainTarget == mainTargetName then
            print(string.format('【%s】 在完成后需要插入的列表中已存在', mainTargetName))
            return true
        end
    end
    local logStr = '成功'
    if insertCond == 2 then
        logStr = '失败'
    elseif insertCond == 3 then
        logStr = '完成'
    end
    print(string.format('在【%s】【%s】后需要插入 【%s】', name, logStr, mainTargetName))
    table.insert(tmpArrData, { data = { mainTarget = mainTargetName, data = mainTargetData }, insertCond = insertCond })
end

--- 【外部】设置当前主目标完成状态
function owner_base:set_cur_main_target_complete_state(isFail)
    self.m_mainTargetData.breakMainTargetData = nil
    local setRes = isFail and true or false
    self.m_mainTargetData.curMainTargetCompleteState = { mainTarget = self.m_mainTargetData.curMainTarget, isFail = setRes }
    self.stateManager:set_curState_leaving()
end

--- 【外部】设置当前状态中断
function owner_base:set_curState_interrupt()
    self.stateManager:set_curState_interrupt()
end

--- 【外部】得到当前状态完成前的运行时间/毫秒
function owner_base:get_curState_runTime()
    return self.stateManager:get_curState_runTime()
end

--- 【外部】得到当前状态完成前的运行时间/毫秒
function owner_base:get_curState_totalRunTime()
    return self.stateManager:get_curState_totalRunTime()
end

--- 【外部】添加计时器
---@param key string 计时器
---@param time number 计时器时间
---@param callback fun() 回调
---@param isClear boolean 是否清除同名的计时器
---@param isFirstCall boolean 是否第一次调用
---@param isLoop boolean 是否循环
function owner_base:add_timer(key, time, callback, isClear, isFirstCall, isLoop)
    self.timerManager:add_timer(key, time, callback, isClear, isFirstCall, isLoop)
end

--- 【外部】得到计时器
function owner_base:get_timer_time(key)
    return self.timerManager:get_time(key)
end

--- 【外部】移除计时器
function owner_base:remove_timer(key)
    self.timerManager:remove_timer(key)
end

--- 【外部】得到计时器
function owner_base:set_timer_defTime(key, time)
    return self.timerManager:set_defTime(key, time)
end

--- 【外部】移除其它目标
function owner_base:remove_other_main_target(mainTargetType)
    local tmpMainTarget = nil
    for _, v in ipairs(self.m_mainTargetData.curMainTargetArr) do
        if mainTargetType == v.mainTarget then
            tmpMainTarget = v
            break
        end
    end
    if tmpMainTarget then
        self.m_mainTargetData.curMainTargetArr = {}
        table.insert(self.m_mainTargetData.curMainTargetArr, tmpMainTarget)
    end
end

--- 【外部】得到当前tick数据
---@param key string 键
---@param func fun() 获取数据的方法
---@return any 返回数据
function owner_base:get_curTickData(key, func)
    if not self.curTickData.data then
        self.curTickData.data = {}
    end
    if self.curTickData.data[key] == nil then
        self.curTickData.data[key] = func()
    end
    return self.curTickData.data[key]
end

-- 设置当前主目标
function owner_base:set_curMainTarget(type)
    self.m_mainTargetData.lastMainTarget = self.m_mainTargetData.curMainTarget
    self.m_mainTargetData.curMainTarget = type
end

-- 获取完成主目标后需要插入的目标
function owner_base:get_complete_mainTarget_from_dic(mainTargetName)
    if self.m_mainTargetData.mainTargetCompleteInsertDic then
        return self.m_mainTargetData.mainTargetCompleteInsertDic[mainTargetName]
    end
    return nil
end

-- 清除完成主目标后需要插入的目标
function owner_base:clear_complete_mainTarget_from_dic_by_name(mainTargetName)
    self.m_mainTargetData.mainTargetCompleteInsertDic[mainTargetName] = nil
end

-- 获取当前目标数量
function owner_base:get_mainTargetArrCount()
    return #self.m_mainTargetData.curMainTargetArr
end

-- 目标列表中是否有目标
function owner_base:is_there_mainTarget_in_mainTargetArr()
    return #self.m_mainTargetData.curMainTargetArr > 0
end

-- 检测目标类型是否在指定索引的目标列表中
function owner_base:check_mainTargetType_from_mainTargetArr(index, type)
    local targetData = self:get_mainTargetData_from_mainTargetArr(index)
    if targetData then
        return targetData.mainTarget == type
    end
    return false
end

-- 获取目标列表中指定索引的目标
function owner_base:get_mainTargetData_from_mainTargetArr(index)
    return self.m_mainTargetData.curMainTargetArr[index]
end

-- 移除目标从目标列表中
function owner_base:remove_mainTarget_from_mainTargetArr(index)
    if self:get_mainTargetArrCount() >= index then
        table.remove(self.m_mainTargetData.curMainTargetArr, index)
    end
end

-- 插入目标到目标列表中
function owner_base:insert_mainTarget_in_mainTargetArr(index, mainTargetData)
    table.insert(self.m_mainTargetData.curMainTargetArr, index, mainTargetData)
end

-- 添加状态
function owner_base:add_state(stateName, state)
    self.stateManager:add_state(stateName, state)
end

-- 更新状态
function owner_base:update_state()
    self.stateManager:update_state()
end

-- 是否状态离开中
function owner_base:is_state_leaving()
    return self.stateManager:is_curState_leaving()
end

--
function owner_base:cancel_isChangeMainTarget()
    self.stateManager:curState_cancel_firstExecute()
end

-- 切换状态
function owner_base:change_state(stateName, isStop)
    self.stateManager:change_state(stateName, isStop)
end

-- 清理当前所有目标数据
function owner_base:clear_all_main_target_data()
    self.m_mainTargetData.curMainTarget = MAIN_TARGET_TYPE.NONE
    self.m_mainTargetData.lastMainTarget = MAIN_TARGET_TYPE.NONE
    self.m_mainTargetData.curMainTargetArr = {}
    self.m_mainTargetData.mainTargetCompleteInsertDic = {}
    self:clear_complete_data()
    self:change_state(MAIN_TARGET_TYPE.NONE)
end

-- 清理当前主目标完成数据
function owner_base:clear_complete_data()
    self.m_mainTargetData.curMainTargetCompleteState = nil
    self.m_mainTargetData.breakMainTargetData = nil
end

-- 获取打断目标数据
function owner_base:get_breakMainTargetData()
    return self.m_mainTargetData.breakMainTargetData
end

-- 设置打断目标数据
function owner_base:set_breakMainTargetData(data)
    self.m_mainTargetData.breakMainTargetData = data
end

-- 获取当前主目标完成状态
function owner_base:get_cur_main_target_complete_state()
    return self.m_mainTargetData.curMainTargetCompleteState
end

-- 初始化当前帧数据
function owner_base:init_tickData(ctx)
    self.curTickData.time = ctx.time
    self.curTickData.data = nil
end

-- 初始化
function owner_base:init(ctx)
    self:clear_data()
    self:on_init(ctx)
end

-- 树运行前刷新
function owner_base:update_data(ctx)
    self:init_tickData(ctx)
    self:check_fail_node()
    self.timerManager:update(ctx.realDeltaTime)
    self:on_update_data(ctx)
end

-- 进入状态机时调用
function owner_base:enter_state(stateName, ctx)
    self:on_enter_state(stateName, ctx)
end

-- 行为树运行前刷新
function owner_base:before_update_state(stateName, ctx)
    self:on_before_update_state(stateName, ctx)
end

-- 更新状态机后调用
function owner_base:last_update_state(stateName, ctx)
    self:on_last_update_state(stateName, ctx)
end

-- 离开状态机时调用
function owner_base:leave_state(stateName, ctx)
    self:clear_complete_data()
    self:on_leave_state(stateName, ctx)
end

-- 行为树运行结束刷新
function owner_base:last_update_data(ctx)
    self:on_last_update_data(ctx)
    self.timerManager:check_all_timer()
end

-- 检查错误节点
function owner_base:check_fail_node()
    if self.failNodes then
        for k, v in pairs(self.failNodes) do
            if v.count >= v.condCount then
                print(string.format('节点[%s]多次返回失败 %s --> %s', v.name, v.count, v.condCount))
                v.count = 0
                self.isFailProperty:set_value(v.name, true)
                return true
            end
        end
    end
    return false
end

-- 添加监听失败的回调
function owner_base:add_record_fail_listen(call)
    self.isFailProperty:add_listen_no_call(call)
end

-- 移除监听失败的回调
function owner_base:remove_record_fail_listen(call)
    self.isFailProperty:remove_listen(call)
end

-- 清理数据时调用
function owner_base:on_clear_data()

end

----------------------脚本运行顺序----------------------
-- 初始化
function owner_base:on_init(ctx)

end

-- 进入状态机时调用
function owner_base:on_enter_state(stateName, ctx)

end

-- 决策树运行前刷新
function owner_base:on_update_data(ctx)

end

-- 决策树运行后 行为树运行前刷新
function owner_base:on_before_update_state(stateName, ctx)

end

-- 行为树运行后刷新
function owner_base:on_last_update_state(stateName, ctx)

end

-- 所有树运行结束刷新
function owner_base:on_last_update_data(ctx)

end

-- 离开状态机时调用
function owner_base:on_leave_state(stateName, ctx)

end

-- new
function owner_base:new()
    local ret = {}
    self.__index = self
    setmetatable(ret, self)
    return ret
end

return owner_base